#include <os/ioremap.h>
#include <os/list.h>
#include <os/mm.h>
#include <pgtable.h>
#include <type.h>

// maybe you can map it to IO_ADDR_START ?
static uintptr_t io_base = IO_ADDR_START;

void *ioremap(unsigned long phys_addr, unsigned long size)
{
    // map phys_addr to a virtual address
    // then return the virtual address
    uintptr_t pgdir = 0xffffffc05e000000;//内核页表
    uintptr_t va,ret=io_base;   
    PTE* pte_first_enrty=pgdir;
    PTE* pte_second_enrty,pte_third_enrty;
    //以下循环体主要抄自alloc_page_helper，只不过将最后叶子填的物理地址由分配换为输入地址
    for(va=io_base;size>0;size-=PAGE_SIZE,va+=PAGE_SIZE,phys_addr+=PAGE_SIZE,io_base+=PAGE_SIZE){
        uintptr_t first_index=((va>>30)) & ~((~0)<< 9);
        uintptr_t second_index=((va)>>21) & ~((~0)<< 9);
        uintptr_t third_index=((va)>>12)& ~((~0)<< 9);
        if(pte_first_enrty[first_index]==0){//如果二级页表不存在则分配一个
            ((PTE*)pte_first_enrty)[first_index]=(allocPage()>>12)<<10|0x1;
        }
        pte_second_enrty=pa2kva((pte_first_enrty[first_index]>>10)<<12);
        if(pte_second_enrty[second_index]==0){//如果三级页表不存在则分配一个
            ((PTE*)pte_second_enrty)[second_index]=(allocPage()>>12)<<10|0x1;
        }
        pte_third_enrty=pa2kva((pte_second_enrty[second_index]>>10)<<12);
        uint64_t flag = _PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_USER;
        ((PTE*)pte_third_enrty)[third_index]=(flag|((phys_addr>>12)<<10));
    }
    return ret;
}

void iounmap(void *io_addr)
{
    // TODO: a very naive iounmap() is OK
    // maybe no one would call this function?
    // *pte = 0;
}
